Completed
Push — master ( 401bbc...02c732 )
by Grant
05:46 queued 02:35
created

SkillDeclarationAPI.populateApplicationUiSkillDeclarations   C

Complexity

Conditions 9
Paths 38

Size

Total Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 9
nc 38
nop 1
dl 0
loc 1
rs 6.6666
c 0
b 0
f 0
1
var SkillDeclarationAPI = {};
2
3
SkillDeclarationAPI.wrapperClass = "applicant-evidence__skill-attribute--required";
4
5
SkillDeclarationAPI.SkillDeclaration = function (criteriaId) {
6
        this.criteria_id = criteriaId;
7
        this.skill_declaration_id = null;
8
        this.skill = null;
9
        this.criteria_type = null;
10
        this.experience_level_id = null;
11
        this.skill_level_id = null;
12
        this.description = null;
13
        this.last_updated = null;
14
15
        /**
16
        * This is valid if experience_level_id, skill_level_id, and description
17
        * are not empty.
18
        *
19
        * @return {Boolean}
20
        */
21
        this.isComplete = function () {
22
            return (this.skill_level_id && this.experience_level_id && this.description );
23
        };
24
        
25
         /**
26
        * Return true if this object is ready to be saved to server
27
        * @return {Boolean}
28
        */
29
        this.isValid = function () {
30
            return this.criteria_id != false;
0 ignored issues
show
Best Practice introduced by
Comparing this.criteria_id to false using the != operator is not safe. Consider using !== instead.
Loading history...
Coding Style introduced by
It is recommended to use !== to compare with false.

Generally, it is recommended to use strict comparison whenever possible and not to rely on the weaker type-juggling comparison operator.

Read more about comparison operations.

Loading history...
31
        };
32
        
33
        this.isEmpty = function () {
34
            return (this.skill_level_id == false && this.experience_level_id == false && this.description == false);
0 ignored issues
show
Best Practice introduced by
Comparing this.experience_level_id to false using the == operator is not safe. Consider using === instead.
Loading history...
Best Practice introduced by
Comparing this.skill_level_id to false using the == operator is not safe. Consider using === instead.
Loading history...
Best Practice introduced by
Comparing this.description to false using the == operator is not safe. Consider using === instead.
Loading history...
Coding Style introduced by
It is recommended to use === to compare with false.

Generally, it is recommended to use strict comparison whenever possible and not to rely on the weaker type-juggling comparison operator.

Read more about comparison operations.

Loading history...
35
        };
36
        
37
        this.nullifyEmptyFields = function() {
38
            this.skill_level_id = this.skill_level_id ? this.skill_level_id : null;
39
            this.experience_level_id = this.experience_level_id ? this.experience_level_id : null;
40
            this.description = this.description ? this.description : null;
41
        };
42
    };
43
44
    SkillDeclarationAPI.loadSavedSkillDeclarationsForJobApplication = function (jobApplicationId) {
45
        DataAPI.getSkillDeclarationsForApplication(jobApplicationId, function (request) {
0 ignored issues
show
Bug introduced by
The variable DataAPI seems to be never declared. If this is a global, consider adding a /** global: DataAPI */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
46
            //Check that request returned a valid response
47
            if (request.status === 200 && request.response) {
48
                var responseJson = JSON.parse(request.response);
49
                var declarations = [];
50
                for (var i = 0; i < responseJson.length; i++) {
51
                    var response = responseJson[i];
52
                    var declaration = new SkillDeclarationAPI.SkillDeclaration(response.criteria_id);
53
                    declaration.skill_declaration_id = response.skill_declaration_id;
54
                    declaration.skill = response.skill;
55
                    declaration.criteria_type = response.criteria_type;
56
                    declaration.experience_level_id = response.experience_level_id;
57
                    declaration.skill_level_id = response.skill_level_id;
58
                    declaration.description = response.description;
59
                    declaration.last_updated = response.last_updated;
60
                    
61
                    declarations.push(declaration);
62
                }
63
                
64
                SkillDeclarationAPI.populateApplicationUiSkillDeclarations(declarations);
65
            }
66
        });
67
    };
68
69
    SkillDeclarationAPI.populateApplicationUiSkillDeclarations = function (skillDeclarations) {
70
        for (var i=0; i<skillDeclarations.length; i++) {
71
            var declaration = skillDeclarations[i];
72
            //find appropriate Evidence Panel
73
            var panel = document.querySelector('.applicant-evidence__skill[data-criteria-id="' + declaration.criteria_id + '"][data-criteria-type="' + declaration.criteria_type + '"]');
74
            //if panel exists, set skill declaration values
75
            if (panel) {
76
                if (declaration.experience_level_id) {
77
                    var experienceSelect = panel.querySelector('input[type="radio"][name="experience"][value="' + declaration.experience_level_id + '"]');
78
                    if (experienceSelect) {
79
                        experienceSelect.checked = true;
80
                    }
81
                }
82
                if (declaration.skill_level_id) {
83
                    var skillLevelSelect = panel.querySelector('input[type="radio"][name="expertise"][value="' + declaration.skill_level_id + '"]');
84
                    if (skillLevelSelect) {
85
                        skillLevelSelect.checked = true;
86
                    }
87
                }
88
89
                var description = panel.querySelector('.applicant-evidence__skill-declaration-text');
90
                if (description) {
91
                    description.value = declaration.description;
92
                }
93
94
                //Run status change handler, because declartion may now be complete
95
                SkillDeclarationAPI.onStatusChange(declaration.criteria_id);
96
                
97
                //If not empty, show status as currently saved
98
                if (!declaration.isEmpty()) {
99
                    EvidenceAPI.setUiSaved(declaration.criteria_id, SkillDeclarationAPI, true);
0 ignored issues
show
Bug introduced by
The variable EvidenceAPI seems to be never declared. If this is a global, consider adding a /** global: EvidenceAPI */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
100
                }
101
            }
102
        }
103
    };
104
105
    SkillDeclarationAPI.populateApplicationPreviewUiSkillDeclarations = function(skillDeclarations) {
106
        for (var i=0; i<skillDeclarations.length; i++) {
107
            var declaration = skillDeclarations[i];
108
            //find appropriate Evidence Panel
109
            var panel = document.querySelector('.applicant-evidence-preview__accordion-wrapper[data-criteria-id="' + declaration.criteria_id + '"]');
110
            //if panel exists, set skill declaration values
111
            if (panel) {
112
                var experience = panel.querySelector('.applicant-evidence-preview__experience');
113
                if (declaration.experience_level_id) {
114
                    experience.innerHTML = LookupAPI.getLocalizedLookupValue("experience_level", declaration.experience_level_id) + " Years";
0 ignored issues
show
Bug introduced by
The variable LookupAPI seems to be never declared. If this is a global, consider adding a /** global: LookupAPI */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
115
                } else {
116
                    experience.innerHTML = null;
117
                }
118
                var skillLevel = panel.querySelector('.applicant-evidence-preview__expertise');
119
                if (declaration.skill_level_id) {
120
                    skillLevel.innerHTML = LookupAPI.getLocalizedLookupValue("skill_level", declaration.skill_level_id);
121
                } else {
122
                    skillLevel.innerHTML = null;
123
                }
124
125
                var description = panel.querySelector('.applicant-evidence-preview__experience-copy');
126
                if (declaration.description) {
127
                    description.innerHTML = declaration.description;
128
                } else {
129
                    description.innerHTML = null;
130
                }
131
            }
132
        }
133
    };
134
135
    /**
136
    * Saves all completed skill declarations of given type.
137
    * If criteriaType is undefined, it saves ALL completed skill declarations.
138
    *
139
    * Call onSuccess if application is saved successfully
140
    *
141
    * @param {string} criteriaType
142
    * @param {function} onSuccess
143
    * @return {undefined}
144
    */
145
    SkillDeclarationAPI.saveSkillDeclarations = function (criteriaType, onSuccess, onFailure) {
146
        if (criteriaType) {
147
            var evidencePanels = document.querySelectorAll(".applicant-evidence__skill[data-criteria-type=\"" + criteriaType + "\"]:not(.template)")
0 ignored issues
show
Coding Style introduced by
There should be a semicolon.

Requirement of semicolons purely is a coding style issue since JavaScript has specific rules about semicolons which are followed by all browsers.

Further Readings:

Loading history...
148
        } else if (criteriaType === undefined) {
149
            var evidencePanels = document.querySelectorAll(".applicant-evidence__skill:not(.template)")
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable evidencePanels already seems to be declared on line 147. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
Bug introduced by
It seems like evidencePanels was already defined.
Loading history...
Coding Style introduced by
There should be a semicolon.

Requirement of semicolons purely is a coding style issue since JavaScript has specific rules about semicolons which are followed by all browsers.

Further Readings:

Loading history...
150
        } else {
151
            Utilities.debug ? console.log("Cannot save Skill Declarations with given type.") : null;
0 ignored issues
show
Debugging Code introduced by
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
Bug introduced by
The variable Utilities seems to be never declared. If this is a global, consider adding a /** global: Utilities */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
Bug introduced by
Did you forget to assign or call a function?

This error message can for example pop up if you forget to assign the result of a function call to a variable or pass it to another function:

function someFunction(x) {
    (x > 0) ? callFoo() : callBar();
}

// JSHint expects you to assign the result to a variable:
function someFunction(x) {
    var rs = (x > 0) ? callFoo() : callBar();
}

// If you do not use the result, you could also use if statements in the
// case above.
function someFunction(x) {
    if (x > 0) {
        callFoo();
    } else {
        callBar();
    }
}
Loading history...
152
            return;
153
        }
154
155
        var submittedRequests = 0; //to keep track of number of PUT calls in progress
156
        var requestsSuccessful = true;
157
158
        var applicationId = document.getElementById("jobApplicationJobApplicationId").value;
159
160
        for (var i=0; i<evidencePanels.length; i++) {
0 ignored issues
show
Bug introduced by
The variable evidencePanels seems to be used out of scope.

This error can usually be fixed by declaring the variable in the scope where it is used:

function someFunction() {
    (function() {
        var i = 0;
    })();

    // i is not defined.
    alert(i);
}

// This can be fixed by moving the var statement to the outer scope.

function someFunction() {
    var i;
    (function() {
        i = 1;
    })();

    alert(i);
};
Loading history...
161
            var panel = evidencePanels[i];
0 ignored issues
show
Bug introduced by
The variable evidencePanels seems to be used out of scope.

This error can usually be fixed by declaring the variable in the scope where it is used:

function someFunction() {
    (function() {
        var i = 0;
    })();

    // i is not defined.
    alert(i);
}

// This can be fixed by moving the var statement to the outer scope.

function someFunction() {
    var i;
    (function() {
        i = 1;
    })();

    alert(i);
};
Loading history...
162
            var newSkillDeclaration = new SkillDeclarationAPI.getSkillDeclarationFromEvidencePanel(panel);
163
164
            if (applicationId) {
165
                //Only save if this declaration is complete
166
                if (newSkillDeclaration.isValid()) {
167
                    submittedRequests = submittedRequests + 1;
168
                    DataAPI.saveSkillDeclaration(newSkillDeclaration, newSkillDeclaration.criteria_id, applicationId, function (response) {
0 ignored issues
show
Bug introduced by
The variable DataAPI seems to be never declared. If this is a global, consider adding a /** global: DataAPI */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
Bug introduced by
It is generally not recommended to make functions within a loop.

While making functions in a loop will not lead to any runtime error, the code might not behave as you expect as the variables in the scope are not imported by value, but by reference. Let’s take a look at an example:

var funcs = [];
for (var i=0; i<10; i++) {
    funcs.push(function() {
        alert(i);
    });
}

funcs[0](); // alert(10);
funcs[1](); // alert(10);
/// ...
funcs[9](); // alert(10);

If you would instead like to bind the function inside the loop to the value of the variable during that specific iteration, you can create the function from another function:

var createFunc = function(i) {
    return function() {
        alert(i);
    };
};

var funcs = [];
for (var i=0; i<10; i++) {
    funcs.push(createFunc(i));
}

funcs[0](); // alert(0)
funcs[1](); // alert(1)
// ...
funcs[9](); // alert(9)
Loading history...
169
                        if (response.status !== 200) {
170
                            requestsSuccessful = false;
171
                        }
172
                        submittedRequests = submittedRequests - 1;
0 ignored issues
show
Bug introduced by
The variable submittedRequests is changed as part of the for loop for example by submittedRequests + 1 on line 167. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
173
                        if (submittedRequests === 0) {
174
                            if (onSuccess && requestsSuccessful) {
0 ignored issues
show
Bug introduced by
The variable requestsSuccessful is changed as part of the for loop for example by false on line 170. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
175
                                //Only call onSuccess if all requests have been successful
176
                                onSuccess();
177
                            } else if (onFailure && !requestsSuccessful) {
178
                                onFailure();
179
                            }
180
                        }
181
                    });
182
                } else {
0 ignored issues
show
Comprehensibility Documentation Best Practice introduced by
This code block is empty. Consider removing it or adding a comment to explain.
Loading history...
183
                    //If declaration is not valid, do nothing
184
                }
185
            }
186
        }
187
188
        if (onSuccess && submittedRequests === 0) {
189
            //If no skills were even attempted to be saved, call onSuccess
190
            onSuccess();
191
        }
192
    };
193
194
    /**
195
    * Saves all completed skill declarations of given type.
196
    * If criteriaType is undefined, it saves ALL completed skill declarations.
197
    *
198
    * Call onSuccess if application is saved successfully
199
    *
200
    * @param {string} skillDeclarationId
201
    * @param {function} onSuccess
202
    * @return {undefined}
203
    */
204
    SkillDeclarationAPI.saveSingleSkillDeclaration = function (skillDeclarationId, onSuccess, onFailure) {
205
206
        var panel = document.querySelector(".applicant-evidence__skill[data-criteria-id=\"" + skillDeclarationId + "\"]:not(.template)")
0 ignored issues
show
Coding Style introduced by
There should be a semicolon.

Requirement of semicolons purely is a coding style issue since JavaScript has specific rules about semicolons which are followed by all browsers.

Further Readings:

Loading history...
207
208
        var applicationId = document.getElementById("jobApplicationJobApplicationId").value;
209
210
        var newSkillDeclaration = new SkillDeclarationAPI.getSkillDeclarationFromEvidencePanel(panel);
211
212
        if (applicationId) {
213
            //Only save if this declaration is complete
214
            if (newSkillDeclaration.isValid()) {
215
                DataAPI.saveSkillDeclaration(newSkillDeclaration, newSkillDeclaration.criteria_id, applicationId, function (response) {
0 ignored issues
show
Bug introduced by
The variable DataAPI seems to be never declared. If this is a global, consider adding a /** global: DataAPI */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
216
                    if (response.status === 200) {
217
                        if (onSuccess)
218
                            onSuccess();
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
219
                    } else {
220
                        if (onFailure) {
221
                            window.alert(response.response.message);
222
                            onFailure();
223
                        }
224
                    }
225
226
                });
227
            } else {
228
                window.alert("Skill declaration invalid, cannot save");
229
            }
230
        }
231
    };
232
233
    SkillDeclarationAPI.getSkillDeclarationFromEvidencePanel = function (panel) {
234
        
235
        var criteria_id = panel.getAttribute("data-criteria-id");;
0 ignored issues
show
Coding Style introduced by
This semicolons seems to be unnecessary.
Loading history...
236
        var skillDeclaration = new SkillDeclarationAPI.SkillDeclaration(criteria_id);
237
238
        skillDeclaration.criteria_type = panel.getAttribute("data-criteria-type");
239
240
        skillDeclaration.skill = panel.querySelector(".applicant-evidence__skill .applicant-evidence__skill-title").innerHTML;
241
242
        var experienceSelect = panel.querySelector('input[name="experience"]:checked'); //This will come back null, if no radio button has been selected yet
243
        skillDeclaration.experience_level_id = experienceSelect ? experienceSelect.value : ""; //Default to an empty string if nothing has been selected
244
245
        var skillLevelSelect = panel.querySelector('input[name="expertise"]:checked'); //This will come back null, if no radio button has been selected yet
246
        skillDeclaration.skill_level_id = skillLevelSelect ? skillLevelSelect.value : ""; //Default to an empty string if nothing has been selected
247
248
        skillDeclaration.description = panel.querySelector('.applicant-evidence__skill-declaration-text').value;
249
        
250
        skillDeclaration.nullifyEmptyFields();
251
        return skillDeclaration;
252
    };
253
254
    SkillDeclarationAPI.onStatusChange = function (criteriaId) {
255
        //If status changes, this can no longer be in a saved state
256
        EvidenceAPI.setUiSaved(criteriaId, SkillDeclarationAPI, false);
0 ignored issues
show
Bug introduced by
The variable EvidenceAPI seems to be never declared. If this is a global, consider adding a /** global: EvidenceAPI */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
257
258
        var panel = document.querySelector(".applicant-evidence__skill[data-criteria-id=\"" + criteriaId + "\"]:not(.template)");
259
260
        var skillDeclaration = SkillDeclarationAPI.getSkillDeclarationFromEvidencePanel(panel);
261
262
        //Use validity to determine Completeness status
263
        EvidenceAPI.setUiComplete(criteriaId, SkillDeclarationAPI, skillDeclaration.isComplete());
264
        
265
        EvidenceAPI.onStatusUpdate();
266
    };
267